package com.market2.session;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.jboss.ejb3.annotation.RemoteBinding;

import com.market2.dto.InvestisseurDto;
import com.market2.dto.OperationDto;
import com.market2.model.Investisseur;
import com.market2.model.Operation;
import com.market2.utils.EntityManagerThreadLocal;
import com.market2.utils.Globals;
import com.market2.utils.converter.ConverterUtil;

/**
 * Session Bean implementation class InvestisseurManager
 */

@Stateless @RemoteBinding(jndiBinding="Market2EAR/InvestisseurManager/remote")
public class InvestisseurManager implements InvestisseurManagerRemote
{
	@PersistenceContext(unitName=Globals.PERSISTENCE_UNIT_NAME)
	private EntityManager entityManager;
	
	@PostConstruct
	void init() {
		EntityManagerThreadLocal.set(entityManager);
	}

	@Override
	public List<InvestisseurDto> getAllInvestisseurs()
	{
		Query query = entityManager.createQuery("from Investisseur");
		
		@SuppressWarnings("unchecked")
		List<Investisseur> queryResult = query.getResultList();
		
		return ConverterUtil.convertTo(queryResult, InvestisseurDto.class);
	}

	@Override
	public InvestisseurDto getInvestisseurByLogin(String login)
	{
		Query query = entityManager.createQuery("from Investisseur inv where inv.login = :login");
		query.setParameter("login", login);
		
		@SuppressWarnings("unchecked")
		List<Investisseur> queryResult = query.getResultList();
		
		if(queryResult.size() == 1) {
			return ConverterUtil.convertTo(queryResult.get(0), InvestisseurDto.class);
		}
		
		return null;
	}
	
	@Override
	public List<InvestisseurDto> getInvestisseurByCriteria(Map<String, Object> criteres)
	{
		if(criteres == null) {
			return new ArrayList<InvestisseurDto>();
		}
		
		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		CriteriaQuery<Investisseur> criteriaQuery = criteriaBuilder.createQuery(Investisseur.class);
		Root<Investisseur> from = criteriaQuery.from(Investisseur.class);
		
		for(String prop : criteres.keySet())
		{
			Object val = criteres.get(prop);
			
			Path<Investisseur> param = from.get(prop);
			Predicate condition = criteriaBuilder.equal(param, val);
			criteriaQuery.where(criteriaBuilder.and(condition));
		}
		
		CriteriaQuery<Investisseur> select = criteriaQuery.select(from);
		TypedQuery<Investisseur> typedQuery = entityManager.createQuery(select);

		List<Investisseur> queryResult = typedQuery.getResultList();
		List<InvestisseurDto> result = ConverterUtil.convertTo(queryResult, InvestisseurDto.class);
		
		return result;
	}

	@Override
	public void enregistrerInvestisseur(InvestisseurDto investisseur)
	{
		if(investisseur == null) {
			return;
		}
		
		Investisseur newInvestisseur = ConverterUtil.convertFrom(investisseur, Investisseur.class);
		entityManager.persist(newInvestisseur);
		entityManager.flush();
	}

	@Override
	public void validerInvestisseur(String login) 
	{
		Investisseur investisseur = entityManager.find(Investisseur.class, login);
		investisseur.setActive(true);
	}

	@Override
	public void invaliderInvestisseur(String login)
	{
		Investisseur investisseur = entityManager.find(Investisseur.class, login);
		investisseur.setActive(false);
	}

	@Override
	public void updateInvestisseur(InvestisseurDto investisseur)
	{
		Investisseur persistantInvestisseur = entityManager.find(Investisseur.class, investisseur.getLogin());
		
		persistantInvestisseur.setLogin(investisseur.getLogin());
		persistantInvestisseur.setPassword(investisseur.getPassword());
		persistantInvestisseur.setNom(investisseur.getNom());
		persistantInvestisseur.setPrenom(investisseur.getPrenom());
		persistantInvestisseur.setEmail(investisseur.getEmail());
		persistantInvestisseur.setAdresse(investisseur.getAdresse());
		persistantInvestisseur.setProfil(investisseur.getProfil());
		
		entityManager.persist(persistantInvestisseur);
		entityManager.flush();
	}

	@Override
	public List<OperationDto> getVentesOfInvestisseur(String login)
	{
		Query query = entityManager.createQuery("SELECT ventes FROM Investisseur as inv JOIN inv.ventes as ventes where inv.login = :login");
		query.setParameter("login", login);
		
		@SuppressWarnings("unchecked")
		List<Operation> queryResult = query.getResultList();
		
		if(queryResult.size() == 1) {
			return ConverterUtil.convertTo(queryResult, OperationDto.class);
		}
		
		return null;
	}

	@Override @SuppressWarnings("unchecked")
	public void setVentesOfInvestisseur(String login, List<OperationDto> ventes)
	{
		Query query = entityManager.createQuery("from Investisseur inv WHERE inv.login = :login").setParameter("login", login);
		List<Investisseur> queryResult = query.getResultList();
		
		Investisseur investisseur;
		
		if(queryResult.size() == 1) {
			investisseur = queryResult.get(0);
		} else {
			return;
		}
		
		List<Operation> newVentes = new ArrayList<Operation>();
		
		for(OperationDto op : ventes) {
			Operation vente = ConverterUtil.convertFrom(op, Operation.class);
			entityManager.persist(vente);
			newVentes.add(vente);
		}
		
		investisseur.setVentes(newVentes);
		entityManager.flush();
	}

	@Override
	public List<OperationDto> getAchatsOfInvestisseur(String login)
	{
		Query query = entityManager.createQuery("SELECT achats FROM Investisseur as inv JOIN inv.achats as achats WHERE inv.login = :login");
		query.setParameter("login", login);
		
		@SuppressWarnings("unchecked")
		List<Operation> queryResult = query.getResultList();
		
		if(queryResult.size() == 1) {
			return ConverterUtil.convertTo(queryResult, OperationDto.class);
		}
		
		return null;
	}

	@Override @SuppressWarnings("unchecked")
	public void setAchatsOfInvestisseur(String login, List<OperationDto> achats)
	{
		Query query = entityManager.createQuery("from Investisseur inv where inv.login = :login").setParameter("login", login);
		List<Investisseur> queryResult = query.getResultList();
		
		Investisseur investisseur;
		
		if(queryResult.size() == 1) {
			investisseur = queryResult.get(0);
		} else {
			return;
		}
		
		List<Operation> newAchats = new ArrayList<Operation>();
		
		for(OperationDto op : achats) {
			Operation achat = ConverterUtil.convertFrom(op, Operation.class);
			entityManager.persist(achat);
			newAchats.add(achat);
		}
		
		investisseur.setAchats(newAchats);
		entityManager.flush();
	}
}
